#ifndef __M_LOOPER_H_
#define __M_LOOPER_H_

#include "buffer.hpp"
#include <thread>
#include <mutex>
#include <condition_variable>
#include<functional>
#include <memory>
#include <atomic>
namespace bitlog
{
    using Funtor = std::function<void(buffer &)>;
    enum class AsyncType
    {
        ASYNC_SAFE,//安全状态
        ASYNC_UNSAFE//非安全状态
    };
    class Asynclooper
    {
        public:
        using ptr = std::shared_ptr<Asynclooper>;
        Asynclooper(const Funtor &callback,AsyncType loopertype):
        _loopertype(AsyncType::ASYNC_SAFE),
        _stop(false)
        ,_callback(callback)
        ,_thread(std::thread(&Asynclooper::threadEntry,this))//需要显示传入this指针
        {}
        void stop()//异步线程停止函数
        {
            _stop=true;
            _cond_con.notify_all();//唤醒所有工作线程
            _thread.join();//等待工作线程的退出
        }
        void push(const char* data, size_t len)//向缓冲区中压入数据
        {
            //注意扩容是非安全状态，主要用于压力测试
            //固定大小--达到极限容量之后就阻塞
            std::unique_lock<std::mutex> lock(_mutex);
            //条件变量的控制：若缓冲区可读数量大于数据长度，那就可以添加数据
             if(_loopertype==AsyncType::ASYNC_SAFE)
            _cond_pro.wait(lock,[&](){return _stop||_product_buff.writesize()>=len;});
            //可以添加数据
            _product_buff.push(data,len);
            //唤醒消费者对缓冲区的数据进行数据处理
            _cond_con.notify_one();
            
        }
        ~Asynclooper()
        {stop();}
        private:
        void threadEntry()//线程入口函数
        {
            while(1)
            {
                //1.判断生产缓冲区有没有数据，有的话就交换到消费缓冲区，没有的话就阻塞
               {
                //给互斥锁一个生命周期
                std::unique_lock<std::mutex> lock(_mutex);
                //若当前是退出前被唤醒，或有数据被唤醒，则返回真，否则继续陷入休眠
              _cond_con.wait(lock,[&](){return !_product_buff.empty();});
              if(_stop&&_product_buff.empty());//防止缓冲区中的数据没有被处理
              break;
              _consumer_buff.swap(_product_buff);
              //唤醒生产者
              _cond_pro.notify_all();
              //括号一出，自动解锁
               }
                //被唤醒后，处理消费缓冲区的数据
                _callback(_consumer_buff);
                //初始化消费缓冲区
                _consumer_buff.reset();
    
            }
        }
        private:
        Funtor _callback;//具体处理回调函数，由使用者自行传入
        private:
        AsyncType _loopertype;
        std::atomic<bool> _stop;//工作器停止标志(原子类型，防止线程安全问题，不加锁以防止代码繁琐)
        buffer _product_buff;//生产者缓冲区
        buffer _consumer_buff;//消费者缓冲区
        std::mutex _mutex;//互斥锁
        std::condition_variable _cond_pro;//生产者等待条件变量
        std::condition_variable _cond_con;//消费者等待条件变量
        std::thread _thread;//异步工作器对应的工作线程
    };
}






#endif